#include "list_piece.h"

piece* creat_piece(int abscisse, int ordonner){

    piece*new = (piece*)malloc(sizeof(piece));
    int static random = 0;
    if (random == 0) {
        random = time(NULL) ;
    }
    srand(random);
    new->R = rand()%180 + 50;
    random=rand();
    srand(random);
    new->G = rand()%180 + 50;
    random=rand();
    srand(random);
    new->B = rand()%180 + 50;
    random=rand();
    new->abscisse = abscisse ;
    new->ordonner = ordonner ;
    new->select = 0 ;
    new->rotation_unique = 1;
    new->inverse_utile = 0;
    new->rotation1 = NULL ;
    new->rotation2 = NULL ;
    new->rotation3 = NULL ;
    new->rotation4 = NULL ;
    new->rotation1i = NULL ;
    new->rotation2i = NULL ;
    new->rotation3i = NULL ;
    new->rotation4i = NULL ;
    new->suivant = NULL ;

    return new;
}


list_piece * creat_list_piece(){

    list_piece * new = (list_piece *)malloc(sizeof(list_piece));
    new->plateau = NULL;
    new->nb_piece = 0;

    return new;
}

list_carre * bonne_rotation(piece * p){
    switch(p->rotation){
        case 1 :
            return  p->rotation1;
        break;
        case 2 :
            return  p->rotation2;
        break;
        case 3 :
            return  p->rotation3;
        break;
        case 4 :
            return  p->rotation4;
        break;
        case -1 :
            return p->rotation1i;
            break;
        case -2 :
            return p->rotation2i;
            break;
        case -3 :
            return p->rotation3i;
            break;
        case -4 :
            return p->rotation4i;
            break;
        default :
            return NULL;
            break;
    }
}

int test_rotation_egales(list_carre * r1, list_carre * r2)
{
    int egaux = 1;
    carre * c_r1 = r1->premier, * c_r2;
    while (c_r1 && egaux == 1) {
        c_r2 = r2->premier ;
        egaux = 0;
        while (c_r2 && egaux == 0) {
            if (c_r1->abscisse == c_r2->abscisse && c_r1->ordonner == c_r2->ordonner) {
                    egaux = 1 ;
            }
            c_r2 = c_r2->suivant ;
        }
        c_r1 = c_r1->suivant ;
    }
    return egaux;
}

list_carre * make_rotation(list_carre * lc, int rotation)
{
  int i, j;
  list_carre * carres = creat_list_carre();
  if (rotation == - 1 || rotation == - 3 || rotation == 3) {
    carres->hauteur = lc->hauteur;
    carres->largeur = lc->largeur;
  } else {
    carres->hauteur = lc->largeur;
    carres->largeur = lc->hauteur;
  }
  carres->pluspetitabsci = -1;
  carre * new_carre = lc->premier;
  while (new_carre != NULL) {
            i = new_carre->abscisse;
            j = new_carre->ordonner;
            switch (rotation) {
            case 1:
              add_carre(carres, i , j) ;
              break;
            case 2:
              add_carre(carres, j , carres->hauteur - i) ;
              break;
            case 3:
              add_carre(carres, carres->largeur - i, carres->hauteur - j) ;
              break;
            case 4:
              add_carre(carres, carres->largeur - j , i) ;
              break;
            case -1:
              add_carre(carres, carres->largeur + 1 - i , j) ;
              break;
            case -2:
              add_carre(carres, carres->largeur - j , carres->hauteur - i) ;
              break;
            case -3:
              add_carre(carres, i , carres->hauteur - j) ;
              break;
            case -4:
              add_carre(carres, j , i) ;
              break;
            }
            if ( (carres->pluspetitabsci == -1) || (carres->pluspetitabsci > carres->premier->abscisse) ) {
                carres->pluspetitabsci = carres->premier->abscisse;
            }
            if ( (carres->pluspetitordo == -1) || (carres->pluspetitordo > carres->premier->ordonner) ) {
                carres->pluspetitordo = carres->premier->ordonner;
            }
            new_carre = new_carre->suivant;
    }
  if ((carres->pluspetitabsci != 0) || (carres->pluspetitordo != 0)) {
    carre * c = carres->premier;
    while(c){
        c->abscisse -= carres->pluspetitabsci;
        c->ordonner -= carres->pluspetitordo;
        c = c->suivant;
    }
  }
  return carres;
}

void make_piece(piece * piece)
{
     int ppa = piece->rotation1->pluspetitabsci;
     if (ppa != 0) {
        carre * c = piece->rotation1->premier;
        while(c){
            c->abscisse -= ppa;
            c = c->suivant;
        }
    }
    piece->rotation = 1;
    piece->rotation2 = make_rotation(piece->rotation1, 2);
    piece->rotation3 = make_rotation(piece->rotation1, 3);
    piece->rotation4 = make_rotation(piece->rotation1, 4);
    piece->rotation1i = make_rotation(piece->rotation1, -1);
    piece->rotation2i = make_rotation(piece->rotation1, -2);
    piece->rotation3i = make_rotation(piece->rotation1, -3);
    piece->rotation4i = make_rotation(piece->rotation1, -4);
    int i, j, egaux;
    list_carre * lc1, * lc2 ;
    for (i = -3; i < 5; i++) {
        if (i != 0) {
            piece->rotation = i ;
            lc1 = bonne_rotation(piece) ;
            egaux = 0 ;
            for (j = -4; j < i; j++) {
                if (j != 0) {
                    piece->rotation = j ;
                    lc2 = bonne_rotation(piece) ;
                    egaux += test_rotation_egales(lc1, lc2) ;
                    if (egaux != 0) {
                        j = 5 ;
                    }
                }
            }
            if (egaux == 0) {
                piece->rotation_unique += 1;
                if (i > 0) {
                    piece->inverse_utile = 1 ;
                }
            }
        }
    }
    piece->rotation = 1;
}

piece * cloner_piece(piece * p)
{
    piece * p_clone = creat_piece(p->abscisse, p->ordonner) ;
    list_carre * rotation1_clone = creat_list_carre() ;
    rotation1_clone->pluspetitabsci = 0 ;
    rotation1_clone->pluspetitordo = 0 ;
    rotation1_clone->largeur = p->rotation1->largeur ;
    rotation1_clone->hauteur = p->rotation1->hauteur ;
    carre * c = p->rotation1->premier;
    while (c) {
        add_carre(rotation1_clone,c->abscisse ,c->ordonner);
        c = c->suivant ;
    }
    p_clone->rotation1 = rotation1_clone ;
    make_piece(p_clone) ;
    return p_clone ;
}

void add_piece(list_piece *l,piece *p)
{
    if(l == NULL){
        exit(EXIT_FAILURE);
    }
    if(l->plateau == NULL){
        l->plateau = p;
        p->suivant = NULL;
    }else{
        piece * c = l->plateau;
        p->suivant = c->suivant;
        c->suivant = p;
    }
    l->nb_piece += 1;
}

void add_piece_precis(list_piece * l, piece * p_ajouter, piece * p_avant)
{
    if (p_avant == NULL) {
            p_ajouter->suivant = l->plateau ;
            l->plateau = p_ajouter ;
    } else if (p_avant == l->plateau) {
            p_ajouter->suivant = l->plateau ->suivant;
            l->plateau->suivant = p_ajouter ;
    } else {
        piece * parcours = l->plateau ;
        while (parcours && parcours != p_avant) {
            parcours = parcours->suivant ;
        }
        if (parcours) {
            p_ajouter->suivant = parcours->suivant ;
            parcours->suivant = p_ajouter ;
        } else {
            p_ajouter->suivant = l->plateau ;
            l->plateau = p_ajouter ;
        }
    }
    l->nb_piece += 1;
}

void jouer_piece(list_piece * reserve,piece *p,list_piece * dejajouer)
{
    piece *jouer = reserve->plateau;
    if(jouer != p){
        while( jouer->suivant != NULL && jouer->suivant != p){
            jouer = jouer->suivant;
        }
        if(jouer->suivant == p){
            piece * tampon = jouer->suivant;
            jouer->suivant = tampon->suivant;
            add_piece(dejajouer, tampon);
        }
    }else{
        reserve->plateau = jouer->suivant;
        add_piece(dejajouer, jouer);
    }
}

void remise_en_jeu(list_piece * reserve,piece *p,list_piece * dejajouer)
{
    piece *jouer = dejajouer->plateau->suivant;
    if(jouer != p){
        while( jouer->suivant != NULL && jouer->suivant != p){
            jouer = jouer->suivant;
        }
        if(jouer->suivant == p){
            piece * tampon = jouer->suivant;
            jouer->suivant = tampon->suivant;
            add_piece(reserve, tampon);
        }
    }else{
        dejajouer->plateau->suivant = jouer->suivant;
        add_piece(reserve, jouer);
    }
}

void remise_en_jeu_precise(list_piece * reserve,piece *p,list_piece * dejajouer, piece *p_avant)
{
    piece *jouer = dejajouer->plateau->suivant;
        if(jouer != p){
            while( jouer->suivant != NULL && jouer->suivant != p){
                jouer = jouer->suivant;
            }
            if(jouer->suivant == p){
                piece * tampon = jouer->suivant;
                jouer->suivant = tampon->suivant;
                add_piece_precis(reserve, tampon, p_avant);
            }
        }else{
            dejajouer->plateau->suivant = jouer->suivant;
            add_piece_precis(reserve, jouer, p_avant);
        }
}

void sup_piece_dans_list(list_piece * l, piece * p)
{
    piece *jouer = l->plateau->suivant;
    if(jouer != p){
        while( jouer->suivant != NULL && jouer->suivant != p){
            jouer = jouer->suivant;
        }
        if(jouer->suivant == p){
            piece * tampon = jouer->suivant;
            jouer->suivant = tampon->suivant;
            supp_list_carre(tampon->rotation1);
            supp_list_carre(tampon->rotation2);
            supp_list_carre(tampon->rotation3);
            supp_list_carre(tampon->rotation4);
            supp_list_carre(tampon->rotation1i);
            supp_list_carre(tampon->rotation2i);
            supp_list_carre(tampon->rotation3i);
            supp_list_carre(tampon->rotation4i);
            free(tampon);
        }
    }else{
        l->plateau->suivant = jouer->suivant;
        supp_list_carre(jouer->rotation1);
        supp_list_carre(jouer->rotation2);
        supp_list_carre(jouer->rotation3);
        supp_list_carre(jouer->rotation4);
        supp_list_carre(jouer->rotation1i);
        supp_list_carre(jouer->rotation2i);
        supp_list_carre(jouer->rotation3i);
        supp_list_carre(jouer->rotation4i);
        free(jouer);
    }
}

void sup_list_piece(list_piece * l){
    piece * tampon;
    while(l->plateau){
        tampon = l->plateau->suivant;

        supp_list_carre(l->plateau->rotation1);
        supp_list_carre(l->plateau->rotation2);
        supp_list_carre(l->plateau->rotation3);
        supp_list_carre(l->plateau->rotation4);
        supp_list_carre(l->plateau->rotation1i);
        supp_list_carre(l->plateau->rotation2i);
        supp_list_carre(l->plateau->rotation3i);
        supp_list_carre(l->plateau->rotation4i);
        free(l->plateau);

        l->plateau = tampon;
    }
    free(l);
}


